package server.schedulables;

import java.nio.channels.ClosedChannelException;
import java.util.List;
import java.util.concurrent.ScheduledFuture;

import common.Player;
import common.Round;

import server.NetworkMediator;
import server.ServerGameState;

public class ScheduledRoundTransitions implements Runnable {

	@SuppressWarnings("unused")
	private final ServerGameState state;
	private final NetworkMediator network;
	private final Round round;
	
	private final static int ONE_MINUTE_IN_MILLIS = 60000;
	
	private ScheduledFuture<?> future;
	
	public ScheduledRoundTransitions( ServerGameState state, NetworkMediator mediator, Round round ) {
		this.state = state;
		this.network = mediator;
		this.round = round;
	}
	
	public void run() {
//		System.out.println("ScheduledRoundTransition running... " + round.getID() + " " + round.getCurrentPhase() );
		long timeNow = System.currentTimeMillis();
		
		long elapsed = timeNow - round.getPhaseStart();
		
		//For each phase of a round, check if it has expired and needs to transition.
		switch( round.getCurrentPhase() ) {
		case REGISTRATION : 
//			if( elapsed >= ONE_MINUTE_IN_MILLIS && round.numberOfPlayers() > 1 ) {
//				// If a minute of time has elapsed and there are players in the round, advance to trading phase.
//				round.changePhase();
//				try {
//					//Update all clients with the new round information
//					network.sendToAllClients( round );
//					
//					//Send all players registered with this round their PlayerLimits that will be restricting their gameplay
//					//during the round.
//					for( Player p : round.getPlayers() ) {
//						network.sendTo( p, p.getLimits() );
//					}
//					
//				} catch (ClosedChannelException e) {
//					System.err.println("ScheduledRoundTransitions: unable to send the round transition to all players!");
//				}
//			} else if( elapsed > ONE_MINUTE_IN_MILLIS ){
//				//If no one registered with this round in the allotted time, restart the phase.
//				round.restartPhase();
//			}
			
			boolean allReady = true;
			
			List<Player> playerList = round.getPlayers();
			synchronized( playerList ) {
				for( Player p : playerList )
					allReady = allReady && p.isReady();
			}
			
			if( allReady && playerList.size() > 1 ) {
				
				round.changePhase();
				
				try {
					network.sendToAllClients( round );
				} catch (ClosedChannelException e) {
					System.err.println("ScheduledRoundTransitions: unable to send the round transition to all players!");
				}
				
				playerList = round.getPlayers();
				for( Player p : playerList )
					try {
						network.sendTo(p, p.getLimits() );
					} catch (ClosedChannelException e) {
						System.err.println("ScheduledRoundTransitions: unable to send the player limits!");
					}
				
			}
			
			break;
		case TRADING : 
			// Trading phase lasts 6 minutes or until all players have satisfied their quota
			if( elapsed >= 6*ONE_MINUTE_IN_MILLIS ) {
				round.changePhase();
				try {
					network.sendToAllClients( round );
				} catch (ClosedChannelException e) {
					System.err.println("ScheduledRoundTransitions: unable to send the round transition to all players!");
				}
			} else {
				List<Player> players = round.getPlayers();
				
				//The list of players will not change during the trading phase (only during the registration phase)
				for( Player p : players )
					if( !p.isDone() )
						return;
				
				// Getting this far means that all players are done trading
				// and the round should change to the results phase
				
				round.changePhase();
				try {
					network.sendToAllClients( round );
				} catch (ClosedChannelException e) {
					System.err.println("ScheduledRoundTransitions: unable to send the round transition to all players!");
				}
			}
			
			break; 
		case RESULTS : 
			
			for( Player p : round.getPlayers() ) {
				network.deregister( p );
				
				p.cancelAllAuctions();
			}
			
			//Stop scheduling this round for transitions
			future.cancel( false );
			break;
		}
	}
	
	public void setScheduledFuture( ScheduledFuture<?> future ) {
		this.future = future;
	}
	
}
